/*********************************************************************
* FileName    : fifo.c
* Dependencies: 
* Processor   : PIC24F
* Complier    : Microchip C30 ,MPLAB IDE v8.90 or higher
* Company     : .
*
* Software License Agreement
*
*
*
* Author : Lau
* Date   : 7/8/2014
********************************************************************/

#include "fifo.h"


/*
*****************************************************************************
* 					FIFO structure define, and Buffer
*****************************************************************************
*/

USR_INT08U	FifoBuf[1024];					// FIFO buffer


USR_INT08U __attribute__((address(0x850))) *Fifo_S;
USR_INT08U __attribute__((address(0x852))) *Fifo_E;
USR_INT08U __attribute__((address(0x854))) *Fifo_R;
USR_INT08U __attribute__((address(0x856))) *Fifo_W;

/*********************************************************************
 * Name        : void FIFO_Init(void)
 * Function    : initial four pointer of the fifo structure
 * PreCondition: None
 * Input       : None
 * Output      : None
 * Side Effects: None
 * Author      : Lau
 * Time/Creat  : 15:50 7/8/2014
 * Time/Modify : 15:50 7/8/2014
 * Note        : None
 ********************************************************************/
void FIFO_Init(void)
{	
    Fifo_S = (USR_INT08U*)FifoBuf;							// pointer to the first item of the buffer
    Fifo_E = (USR_INT08U*)FifoBuf + sizeof(FifoBuf)-1;		// pointer to the last item of the buffer
    Fifo_R = Fifo_S;										// pointer to the first available item that is readable
	Fifo_W = Fifo_S;										// pointer to the first available item that is writeable
}

/*********************************************************************
 * Name        : USR_INT16S FIFO_Read(USR_INT08U* pBuffer,USR_INT16S len )
 * Function    : read data from fifo, and put the data to pBuffer
 * PreCondition: None
 * Input       : pBuffer dest data buffer, len dest data buffer length
 * Output      : -1 error, tCtr the number had read
 * Side Effects: None
 * Author      : Lau
 * Time/Creat  : 15:50 7/8/2014
 * Time/Modify : 15:50 7/8/2014
 * Note        : None
 ********************************************************************/
USR_INT16S FIFO_Read(USR_INT08U* pBuffer,USR_INT16S len )
{
	USR_INT16S tCtr;
	if(pBuffer == USR_NULL)
		return -1;
	
	tCtr = FIFO_HoldNum();
	len = tCtr = MIN(tCtr, len);
	U1RXI_DIS();            // disable high level priority interrupt
	while( tCtr > 0 )
    {
        // read from the FIFO, and pointe to the next
        *pBuffer++ = *Fifo_R;
        // check if it is the bottom of FIFO
        if( Fifo_R >= Fifo_E )
        {
           Fifo_R = Fifo_S;
        }
		else
			Fifo_R ++;
			
		tCtr --;
    }
	U1RXI_EN();            // enable high level priority interrupt
	return len;
}

/*********************************************************************
 * Name        : USR_INT16S FIFO_Write(USR_INT08U* pBuffer,USR_INT16S len )
 * Function    : write data to fifo, source data in pBuffer
 * PreCondition: None
 * Input       : pBuffer source data buffer, len the length of data wanted to be written
 * Output      : -1 error, tCtr the number had written
 * Side Effects: None
 * Author      : Lau
 * Time/Creat  : 15:50 7/8/2014
 * Time/Modify : 15:50 7/8/2014
 * Note        : None
 ********************************************************************/
USR_INT16S FIFO_Write(USR_INT08U* pBuffer,USR_INT16S len )
{
	USR_INT16S tCtr;
	if(pBuffer == USR_NULL)
		return -1;
		
	tCtr = FIFO_BlankNum();
	tCtr = MIN(tCtr, len);
	U1RXI_DIS();            // disable high level priority interrupt
    while( tCtr > 0 )
    {
        // write to the FIFO, and pointe to the next
 		*Fifo_W = *pBuffer++;
        // check if it is the bottom of FIFO
 		if( Fifo_W >= Fifo_E )
 		{
 			Fifo_W = Fifo_S;
 		}
		else
			Fifo_W ++;
			
		tCtr --;
    }
	U1RXI_EN();            // enable high level priority interrupt
	return tCtr;
}

/*********************************************************************
 * Name        : USR_INT16S FIFO_BlankNum(void)
 * Function    : computer the number of blank in fifo
 * PreCondition: None
 * Input       : 
 * Output      : wBlankNum the number of blank
 * Side Effects: None
 * Author      : Lau
 * Time/Creat  : 15:50 7/8/2014
 * Time/Modify : 15:50 7/8/2014
 * Note        : None
 ********************************************************************/
USR_INT16S FIFO_BlankNum(void)
{
	USR_INT16S wBlankNum;
    U1RXI_DIS();            // disable high level priority interrupt
	if( Fifo_W == Fifo_R )
	    wBlankNum = Fifo_E - Fifo_S + 1;
	else if( Fifo_W > Fifo_R )
	    wBlankNum = Fifo_E - Fifo_S + Fifo_R - Fifo_W;
	else
	    wBlankNum = Fifo_R - Fifo_W;
   	U1RXI_EN();            // enable high level priority interrupt
	return wBlankNum;

}

/*********************************************************************
 * Name        : USR_INT16S FIFO_HoldNum(void)
 * Function    : computer the number of data in fifo
 * PreCondition: None
 * Input       : 
 * Output      : wHoldNum the number of data
 * Side Effects: None
 * Author      : Lau
 * Time/Creat  : 15:50 7/8/2014
 * Time/Modify : 15:50 7/8/2014
 * Note        : None
 ********************************************************************/
USR_INT16S FIFO_HoldNum(void)
{
    USR_INT16S wHoldNum;
    U1RXI_DIS();            // disable high level priority interrupt
    if( Fifo_W == Fifo_R )
        wHoldNum = 0;
    else if( Fifo_W > Fifo_R )
        wHoldNum = Fifo_W - Fifo_R;
    else
        wHoldNum = Fifo_E - Fifo_S + Fifo_W - Fifo_R;
   	U1RXI_EN();            // enable high level priority interrupt
	return wHoldNum;
}
